package com.yanqu.road.server.gameplayer.module.player;

import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogTradeWarBuildingReward;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.task.args.TradeWarBuildingArgs;
import com.yanqu.road.entity.tradewar.*;
import com.yanqu.road.logic.bussiness.player.UserTradeWarBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.TradeWarPb;
import com.yanqu.road.pb.tradewar.TradeWarProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.manger.DataAnalyticsMgr;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigInteger;
import java.util.*;

public class TradeWarBuildingModule extends GeneralModule {

    public TradeWarBuildingModule(GamePlayer player) {
        super(player);
    }

    private Map<Integer, UserTradeWarBuilding> userTradeWarBuildingMap;

    private final Object calcLock = new Object();

    @Override
    public boolean saveData() {
        if (null != userTradeWarBuildingMap){
            for(UserTradeWarBuilding userTradeWarBuilding : userTradeWarBuildingMap.values()) {
                if (userTradeWarBuilding.isInsertOption()) {
                    UserTradeWarBussiness.addUserTradeWarBuilding(userTradeWarBuilding);
                } else if (userTradeWarBuilding.isUpdateOption()) {
                    UserTradeWarBussiness.updateUserTradeWarBuilding(userTradeWarBuilding);
                }
            }
        }
        return true;
    }

    @Override
    public boolean loadData() {
        userTradeWarBuildingMap = UserTradeWarBussiness.getUserTradeWarBuildingMap(player.getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        if(SystemOpenMgr.systemOpen(player, eSystemId.TradeWar.getValue())) {
            initTaxOffice();
        }
        return true;
    }

    @Override
    public void afterLogin() {
        if(null != userTradeWarBuildingMap){
            syncTradeWarBuilding(new ArrayList<>(userTradeWarBuildingMap.values()));
        }
    }

    @Override
    public void loginSendMsg() {

    }

    public void initTradeWarBuildingSystem(){
        initTaxOffice();
        if(null != userTradeWarBuildingMap){
            syncTradeWarBuilding(new ArrayList<>(userTradeWarBuildingMap.values()));
        }
    }

    /**
     * 同步钱庄信息
     */
    private void syncTradeWarBuilding(UserTradeWarBuilding userTradeWarBuilding){
        if(null != userTradeWarBuilding){
            List<UserTradeWarBuilding> syncList = new ArrayList<>();
            syncList.add(userTradeWarBuilding);
            syncTradeWarBuilding(syncList);
        }
    }

    /**
     * 同步钱庄信息
     */
    private void syncTradeWarBuilding(List<UserTradeWarBuilding> userTradeWarBuildingList){
        TradeWarProto.TradeWarBuildingListMsg.Builder listMsg = TradeWarPb.parseTradeWarBuildingListMsg(userTradeWarBuildingList);
        if(listMsg.getBuildingListCount() > 0){
            long nowTime = System.currentTimeMillis() / 1000;
            for(TradeWarProto.TradeWarBuildingTempMsg.Builder msg : listMsg.getBuildingListBuilderList()) {
                BigInteger value = calcBuildingReward(msg.getType(), nowTime);
                msg.setValue(value.toString());
                msg.setLastCalcRewardTime(nowTime);
            }
        }
        player.sendPacket(Protocol.U_TRADE_WAR_BUILDING_SYNC, listMsg);
    }

    /**
     * 初始化商战建筑，税所
     */
    private void initTaxOffice(){
        if(null == userTradeWarBuildingMap || !userTradeWarBuildingMap.containsKey(eTradeWarBuildingType.TaxOffice.getValue())){
            UserTradeWarBuilding userTradeWarBuilding = initUserTradeWarBuilding(eTradeWarBuildingType.TaxOffice.getValue(),
                    player.getModule(EarnSpeedModule.class).getEarnSpeed());
            userTradeWarBuildingMap.put(userTradeWarBuilding.getType(), userTradeWarBuilding);
            //成就、任务
            player.notifyListener(eGamePlayerEventType.TaxOfficeLevel.getValue(), userTradeWarBuilding);
        }
    }

    /**
     * 商战建筑升级，返回收益
     */
    public Property buildingUpgrade(int type){
        long nowTime = System.currentTimeMillis() / 1000;
        Property reward = getBuildingReward(type, nowTime, true);
        UserTradeWarBuilding userTradeWarBuilding = getUserTradeWarBuilding(type);
        TradeWarBuilding nextTradeWarBuilding = TradeWarConfigMgr.getTradeWarBuilding(type, userTradeWarBuilding.getLevel() + 1);
        //增加等级
        userTradeWarBuilding.setLevel(userTradeWarBuilding.getLevel() + 1);
        BigInteger outputSpeed;
        long rewardTime;
        long lastGetTime;
        if(eTradeWarBuildingType.TaxOffice.getValue() == type){
            outputSpeed = player.getModule(EarnSpeedModule.class).getEarnSpeed();
            rewardTime = 60 * nextTradeWarBuilding.getGetRewardMaxTime();
            lastGetTime = nowTime - rewardTime;
            //成就、任务
            player.notifyListener(eGamePlayerEventType.TaxOfficeLevel.getValue(), userTradeWarBuilding);
        }else {
            return null;
        }
        outputSpeed = outputSpeed.multiply(BigInteger.valueOf(nextTradeWarBuilding.getOutputSpeedParam())).divide(BigInteger.valueOf(1000));
        //升级将受益初始化为满状态
        userTradeWarBuilding.setLastValue(outputSpeed.multiply(BigInteger.valueOf(rewardTime)));
        userTradeWarBuilding.setLastValueChangeTime(nowTime);
        userTradeWarBuilding.setLastGetTime(lastGetTime);
        syncTradeWarBuilding(userTradeWarBuilding);

        DataAnalyticsMgr.trackOreWarTaxOffice(player, userTradeWarBuilding.getLevel());
        return reward;
    }

    /**
     * 领取建筑收益
     */
    public Property getBuildingReward(int type, long getRewardTime, boolean isAutoGet){
        Property reward = new Property();
        UserTradeWarBuilding userTradeWarBuilding = getUserTradeWarBuilding(type);
        if(null == userTradeWarBuilding){
            return reward;
        }
        BigInteger value = calcBuildingReward(type, getRewardTime);
        if (eTradeWarBuildingType.TaxOffice.getValue() == type) {
            reward.addProperty(GameConfig.GAME_MONEY_SILVER, value);
        } else {
            return reward;
        }
        //更新税所信息
        userTradeWarBuilding.setLastValue(BigInteger.ZERO);
        userTradeWarBuilding.setLastGetTime(getRewardTime);
        if(!isAutoGet) {
            userTradeWarBuilding.setTotalGetRewardTimes(userTradeWarBuilding.getTotalGetRewardTimes() + 1);
            //成就、任务
            player.notifyListener(eGamePlayerEventType.TradeWarBuildingTotalGetRewardTimes.getValue(), new TradeWarBuildingArgs(userTradeWarBuildingMap));
        }
        //收益入口袋
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.TradeWar, eLogMoneyType.TradeWarBuildingReward);
        AutoLogMgr.add(new LogTradeWarBuildingReward(player.getUserId(), type, PropertyHelper.parsePropertyToString(reward), isAutoGet));
        syncTradeWarBuilding(userTradeWarBuilding);
        log.info("userId:{} get trade war building type:{} value:{} isAuto:{}", player.getUserId(), type, value.toString(), isAutoGet);
        try {
            if(type == eTradeWarBuildingType.TaxOffice.getValue()){
                silverRecoveryTime();
            }
        }catch (Exception e){
            log.error("error:" + e);
        }
        return reward;
    }

    private UserTradeWarBuilding initUserTradeWarBuilding(int type, BigInteger outputSpeed) {
        long nowTime = System.currentTimeMillis() / 1000;
        UserTradeWarBuilding userTradeWarBuilding = new UserTradeWarBuilding();
        userTradeWarBuilding.setUserId(player.getUserId());
        userTradeWarBuilding.setType(type);
        userTradeWarBuilding.setLevel(1);
        //初始化可收取的最大值
        TradeWarBuilding tradeWarBuilding = TradeWarConfigMgr.getTradeWarBuilding(userTradeWarBuilding.getType(), userTradeWarBuilding.getLevel());
        BigInteger newOutputSpeed = outputSpeed.multiply(BigInteger.valueOf(tradeWarBuilding.getOutputSpeedParam())).divide(BigInteger.valueOf(1000));
        long rewardTime = 60 * tradeWarBuilding.getGetRewardMaxTime();
        long lastGetTime = nowTime - rewardTime;
        userTradeWarBuilding.setLastGetTime(lastGetTime);
        userTradeWarBuilding.setLastValue(newOutputSpeed.multiply(BigInteger.valueOf(rewardTime)));
        userTradeWarBuilding.setLastValueChangeTime(nowTime);
        userTradeWarBuilding.setInsertOption();
        return userTradeWarBuilding;
    }

    private void silverRecoveryTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        long recoveryTime = 0;
        int type = eTradeWarBuildingType.TaxOffice.getValue();
        UserTradeWarBuilding userTradeWarBuilding = getUserTradeWarBuilding(type);
        if(userTradeWarBuilding == null){
            return;
        }
        TradeWarBuilding tradeWarBuilding = TradeWarConfigMgr.getTradeWarBuilding(type, userTradeWarBuilding.getLevel());
        if(tradeWarBuilding == null){
            return;
        }
        long startTime = userTradeWarBuilding.getLastValueChangeTime();
        if (startTime < userTradeWarBuilding.getLastGetTime()) {
            startTime = userTradeWarBuilding.getLastGetTime();
        }
        long rewardMaxTime = 60L * tradeWarBuilding.getGetRewardMaxTime();

        recoveryTime = (startTime + rewardMaxTime) * 1000;

        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setPatronsWarSilverTime(recoveryTime);
    }
    /**
     * 计算钱庄收益
     */
    BigInteger calcBuildingReward(int type, long calcTime) {
        BigInteger value = BigInteger.ZERO;
        UserTradeWarBuilding userTradeWarBuilding = getUserTradeWarBuilding(type);
        if(null == userTradeWarBuilding) {
            return value;
        }
        boolean isNoLimit = false;
        if(player.getModule(CardModule.class).isTaxOfficeOutputNoLimit() && eTradeWarBuildingType.TaxOffice.getValue() == type){
            isNoLimit = true;
        }
        BigInteger outputSpeed;
        if(eTradeWarBuildingType.TaxOffice.getValue() == type){
            outputSpeed = player.getModule(EarnSpeedModule.class).getEarnSpeed();
        }else {
            return value;
        }
        TradeWarBuilding tradeWarBuilding = TradeWarConfigMgr.getTradeWarBuilding(type, userTradeWarBuilding.getLevel());
        outputSpeed = outputSpeed.multiply(BigInteger.valueOf(tradeWarBuilding.getOutputSpeedParam())).divide(BigInteger.valueOf(1000));
        synchronized (calcLock) {
            long canGetTime;
            long startTime = userTradeWarBuilding.getLastValueChangeTime();
            if (startTime < userTradeWarBuilding.getLastGetTime()) {
                startTime = userTradeWarBuilding.getLastGetTime();
            }
            if(isNoLimit){
                canGetTime = calcTime - startTime;
                value = getCalcValue(calcTime, userTradeWarBuilding, outputSpeed, canGetTime);
            }else {
                long rewardMaxTime = 60 * tradeWarBuilding.getGetRewardMaxTime();
                if (startTime - userTradeWarBuilding.getLastGetTime() < rewardMaxTime) {
                    if (calcTime - userTradeWarBuilding.getLastGetTime() < rewardMaxTime) {
                        canGetTime = calcTime - startTime;
                    } else {
                        canGetTime = userTradeWarBuilding.getLastGetTime() + rewardMaxTime - startTime;
                    }
                    value = getCalcValue(calcTime, userTradeWarBuilding, outputSpeed, canGetTime);
                } else {
                    if (!Objects.equals(userTradeWarBuilding.getLastOutputSpeed(), outputSpeed)) {//产出变化了
                        userTradeWarBuilding.setLastOutputSpeed(outputSpeed);
                        userTradeWarBuilding.setLastValueChangeTime(calcTime);
                    }
                    value = userTradeWarBuilding.getLastValue();
                }
            }
        }
        return value;
    }

    private BigInteger getCalcValue(long calcTime, UserTradeWarBuilding userTradeWarBuilding, BigInteger outputSpeed, long canGetTime) {
        BigInteger value;
        if (canGetTime < 0) {
            canGetTime = 0;
        }
        if (!Objects.equals(userTradeWarBuilding.getLastOutputSpeed(), outputSpeed)) {//产出变化了
            userTradeWarBuilding.setLastValue(userTradeWarBuilding.getLastValue().add(userTradeWarBuilding.getLastOutputSpeed().
                    multiply(BigInteger.valueOf(canGetTime))));
            userTradeWarBuilding.setLastOutputSpeed(outputSpeed);
            userTradeWarBuilding.setLastValueChangeTime(calcTime);
            value = userTradeWarBuilding.getLastValue();
        } else {
            value = userTradeWarBuilding.getLastValue().add(userTradeWarBuilding.getLastOutputSpeed().multiply(BigInteger.valueOf(canGetTime)));
        }
        return value;
    }

    public UserTradeWarBuilding getUserTradeWarBuilding(int type) {
        return userTradeWarBuildingMap.get(type);
    }

    public Map<Integer, UserTradeWarBuilding> getUserTradeWarBuildingMap() {
        return userTradeWarBuildingMap;
    }

    /**
     * 计算税所找回的收益
     */
    public BigInteger getSliverRecoveryValue(int param, int days) {
        BigInteger value = BigInteger.ZERO;
        UserTradeWarBuilding userTradeWarBuilding = getUserTradeWarBuilding(eTradeWarBuildingType.TaxOffice.getValue());
        if (userTradeWarBuilding == null){
            return value;
        }

        TradeWarBuilding tradeWarBuilding = TradeWarConfigMgr.getTradeWarBuilding(eTradeWarBuildingType.TaxOffice.getValue(), userTradeWarBuilding.getLevel());
        if (tradeWarBuilding == null){
            log.error("玩家{}找回商战银两时获取税所配置等级 {}错误 !!!",getUserId(),userTradeWarBuilding.getLevel());
            return value;
        }
        //玩家税所生产速度
        BigInteger outputSpeed = player.getModule(EarnSpeedModule.class).getEarnSpeed();
        outputSpeed = outputSpeed.multiply(BigInteger.valueOf(tradeWarBuilding.getOutputSpeedParam())).divide(BigInteger.valueOf(1000));
        //最后收货时间
        long lastGetTime = userTradeWarBuilding.getLastGetTime() * 1000;
        //下线后一天0点
        long lastRecodeTime = DateHelper.getTodayZeroTimeStamp() - days * DateHelper.DAY_MILLIONS;
        //最多时间
        long rewardMaxTime = 60 * tradeWarBuilding.getGetRewardMaxTime() * 1000;
        //总共找回时间
        long totalRecoveryTime = days * rewardMaxTime;
        //差值
        long difference = lastGetTime + rewardMaxTime - lastRecodeTime;
        if (difference > 0){ //离线时还未满
            if (difference > totalRecoveryTime){
                return value;
            }else {
                value = BigInteger.valueOf(totalRecoveryTime - difference);
            }
        }else {
            value = BigInteger.valueOf(totalRecoveryTime);
        }
        if (value.compareTo(BigInteger.ZERO) > 0){
            value = value.divide(BigInteger.valueOf(1000));
            value = outputSpeed.multiply(value.multiply(BigInteger.valueOf(param)).divide(BigInteger.valueOf(1000)));
            return value;
        }
        return BigInteger.ZERO;
    }

}
